#ifndef MATRIX_H
#define MATRIX_H

#include <iostream>
#include <QtGui>

template<typename Type>
struct LinkedItem
{
	LinkedItem() : next(0) {}
	LinkedItem(Type d, LinkedItem<Type> *n = 0) : data(d), next(n) { }

	Type data;
	LinkedItem<Type> *next;
};

template<typename HeaderType, typename DataType>
class Matrix
{
	HeaderType *head;
	unsigned int size;
	LinkedItem<DataType*> *matrixData;
public:
	Matrix(unsigned int s) : size(s), matrixData(0)
	{
		head = new HeaderType[s];
	}

	unsigned int getSize() const
	{
		return size;
	}

	void setHead(const HeaderType* header)
	{
		if (head && header)
		{
			for (unsigned int i=0;i<size;++i)
			{
				head[i]=header[i];
			}
		}
	}

	void addRow(const DataType* row)
	{
		if (matrixData && row)
		{
			LinkedItem<DataType*> *p=matrixData;
			while (p->next)
			{
				p=p->next;
			}
			p->next = new LinkedItem<DataType*>();
			DataType *array = new DataType[size];
			for (unsigned int i=0;i<size;++i)
			{
				array[i]=row[i];
			}
			p->next->data=array;
		}
		else
		{
			matrixData = new LinkedItem<DataType*>();
			DataType * array = new DataType[size];
			for (unsigned int i = 0;i<size;++i)
			{
				array[i] = row[i];
			}
			matrixData->data=array;
		}
	}

	friend std::ostream& operator << (std::ostream& str, const Matrix& matrix)
        {
            for (unsigned int i=0;i<matrix.size;++i)
            {
                str <<matrix.head[i] << " ";
            }
            str << std::endl;
            LinkedItem<DataType*> *p = matrix.matrixData;
            while (p)
            {
                for (unsigned int i=0;i<matrix.size;++i)
                {
                    if (p->data[i]==INT_MAX) str << "+inf";
                    else str << p->data[i];
                    str << " ";
                }
                p=p->next;
                str << std::endl;
            }
            return str;
	}

        friend QTextStream& operator << (QTextStream& str, const Matrix& matrix)
        {
            for (unsigned int i=0;i<matrix.size;++i)
            {
                str << matrix.head[i] << " ";
            }
            str << "\n";
            LinkedItem<DataType*> *p = matrix.matrixData;
            while (p)
            {
                for (unsigned int i=0;i<matrix.size;++i)
                {
                    if (p->data[i]==INT_MAX) str << "+inf";
                    else str << p->data[i];
                    str << " ";
                }
                p=p->next;
                str << "\n";
            }
            return str;
        }

};


#endif // MATRIX_H
